<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://doc.hyperf.io
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
 */

namespace App\Model;

use App\Exception\DatabaseExceptionHandler;
use Hyperf\Database\Model\Events\Updated;
use Hyperf\ModelCache\Cacheable;
use App\Common\Traits\Table;

abstract class BaseModel extends Model
{
    /**
     * The name of the "deleted_at" column.
     *
     * @var string
     */
    const FIELD_ID       = 'id';
    const FIELD_VERSION  = 'version';

    const FIELD_DELETED_AT = 'deleted_at';
    const FIELD_CREATED_AT = 'created_at';
    const FIELD_UPDATED_AT = 'updated_at';

    /**
     *可操作的开关字段白名单
     * @var array
     */
    protected $switchList = ['status'];

    use Cacheable;
    use Table;

    /**
     * getInfo
     * 通过主键id/ids获取信息
     * @param $id
     * @param bool $useCache 是否使用模型缓存
     * @return BaseModel|\Hyperf\Database\Model\Model|null
     */
    public function getInfo($id, $useCache = true)
    {
        $instance = make(get_called_class());

        if ($useCache === true) {
            $modelCache = is_array($id) ? $instance->findManyFromCache($id) : $instance->findFromCache($id);
            return isset($modelCache) && $modelCache ? $modelCache->toArray() : [];
        }

        return $instance->query()->find($id);
    }


    /**
     * @param int $id
     * @param array $field
     * @return \Hyperf\Database\Model\Builder|\Hyperf\Database\Model\Model|object|null
     */
    public function getOne(int $id, array $field=['*'])
    {
        return $this->where(['id'=>$id])->select($field)->first();
    }

    /**
     * 新增记录
     * @param array $map
     * @return bool
     */
    public function saveModel(array $map)
    {
        if(!isset($map) && !$map) {
            throw new DatabaseExceptionHandler(9001, '新增记录数据异常');
        }
        return $this->insert($map);
    }

    /**
     * 编辑记录
     * @param BaseModel $model
     * @param array $map
     * @return int
     */
    public function updateModel($model, array $map)
    {
        $id = $model->getAttribute(self::FIELD_ID);
        $version = $model->getAttribute(self::FIELD_VERSION);
        if(!$id || !$map) {
            throw new DatabaseExceptionHandler(9002, '编辑记录数据异常');
        }
        return $this->where([[self::FIELD_ID, $id], [self::FIELD_VERSION, $version]])->update(array_merge($map, [self::FIELD_VERSION=>$version + 1]));
    }


    /**
     * getInfoByWhere
     * 根据条件获取结果
     * @param $where
     * @param bool $type 是否查询多条
     * @return array
     */
    public function getInfoByWhere($where, $type = false)
    {
        $instance = make(get_called_class());
        foreach ($where as $k => $v) {
            $instance = is_array($v) ? $instance->where($k, $v[0], $v[1]) : $instance->where($k, $v);
        }
        $instance = $type ? $instance->get() : $instance->first();
        return $instance ? $instance->toArray() : [];
    }

    /**
     * deleteInfo
     * 删除/恢复
     * @param $ids 删除的主键ids
     * @param string 删除delete/恢复restore
     * @return int
     */
    public function deleteInfo($ids, $type = 'delete')
    {
        $instance = make(get_called_class());
        if ($type == 'delete') {
            return $instance->destroy($ids);
        }
        else {
            $count = 0;
            $ids = is_array($ids) ? $ids : [$ids];
            foreach ($ids as $id) {
                if ($instance::onlyTrashed()->find($id)->restore()) {
                    ++$count;
                }
            }

            return $count;
        }
    }

    /**
     * getPagesInfo
     * 获取分页信息，适用于数据量小
     * 数据量过大，可以采用服务层调用，加入缓存
     * @param $where
     * @return array
     */
    public function getPagesInfo($where = [], $count = true)
    {
        $pageSize = 10;
        $currentPage = 1;
        if (isset($where['page_size'])) {
            $pageSize = $where['page_size'] > 0 ? $where['page_size'] : 10;
            unset($where['page_size']);
        }
        if (isset($where['current_page'])) {
            $currentPage = $where['current_page'] > 0 ? $where['current_page'] : 1;
            unset($where['current_page']);
        }

        $offset = ($currentPage - 1) * $pageSize;

        if ($count) {
            $total = $this->getCount($where);
        }

        return [
            'current_page' => (int)$currentPage,
            'offset' => (int)$offset,
            'page_size' => (int)$pageSize,
            'total' => $count ? (int)$total : 0,
        ];
    }

    /**
     * getCount
     * 根据条件获取总数
     * @param array $where
     * @return int
     */
    public function getCount($where = [])
    {
        $instance = make(get_called_class());

        foreach ($where as $k => $v) {
            if ($k === 'title') {
                $instance = $instance->where($k, 'LIKE', '%' . $v . '%');
                continue;
            }
            $instance = $instance->where($k, $v);
        }

        $count = $instance->count();

        return $count > 0 ? $count : 0;
    }
}
